using Crux.Core.Payloads;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace Crux.Core.Jwt;
/// <inheritdoc/>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public abstract class JwtAuthorizationFilter : Attribute, IAsyncAuthorizationFilter
{
    /// <inheritdoc/>
    public virtual string GetSignal() => "Bearer";
    /// <inheritdoc/>
    public virtual bool ExtremeDemand() => true;
    /// <inheritdoc/>
    protected abstract JwtOption GetOption(IServiceProvider serviceProvider);
    /// <inheritdoc/>
    public Task OnAuthorizationAsync(AuthorizationFilterContext context)
    {
        try
        {
            var signal = GetSignal();

            if (!context.HttpContext.Request.Headers.TryGetValue("Authorization", out var tokenStringValues))
            {
                throw new UnauthorizedException("TokenIsEmpty");
            }

            var token = tokenStringValues.FirstOrDefault();
            if (!(token?.StartsWith(signal) ?? false))
            {
                throw new UnauthorizedException("TokenIsEmpty");
            }

            token = token!.Substring(signal.Length).Trim();

            var option = GetOption(context.HttpContext.RequestServices);

            context.HttpContext.User = JwtResolver.Resolve(option, token, out _);
        }
        catch (UnauthorizedException e)
        {
            if (this.ExtremeDemand())
            {
                var payload = Payload.Unauthorized(e.Message);

                var result = new ObjectResult(payload);
                result.StatusCode = 403;

                context.Result = result;

                context.HttpContext.Response.StatusCode = 403;
            }
            else
            {
                throw;
            }
        }
        return Task.CompletedTask;
    }

}